package lambada表达式;

import lambada表达式.entity.OutstandingClass;
import lambada表达式.entity.SpecialityEnum;
import lambada表达式.entity.Student;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/*lambada表达式的使用*/
public class Test {

    public static void main(String[] args) {
        /* 常用的流操作 */
        test1();
        /* 高级集合类及收集器 */
        test2();
    }

    /* 常用的流操作 */
    public static void test1() {
        /* collect(Collectors.toList()) */
        List<Student> students = Stream.of(new Student("路飞", 22, 175),
                new Student("红发", 40, 180),
                new Student("白胡子", 50, 185))
                .collect(Collectors.toList());
        System.out.println("collect(Collectors.toList())：" + students);
        /* filter */
        List<Student> students2 = students.stream()
                .filter(stu -> stu.getStature() < 180)
                .collect(Collectors.toList());
        System.out.println("filter：" + students2);
        /* map */
        List<String> names = students.stream()
                .map(student -> student.getName())
                .collect(Collectors.toList());
        System.out.println("map：" + names);
        /* flatMap将两个集合合并为一个 */
        List<Student> students3 = Stream.of(students,
                Stream.of(new Student("艾斯", 25, 183),
                        new Student("雷利", 48, 176))
                        .collect(Collectors.toList()))
                .flatMap(list -> list.stream()).collect(Collectors.toList());
        System.out.println("flatMap：" + students3);
        /* max和min，尽量使用jdk自带的api，而不是自己写实现，例如这里的比较器 */
        Optional<Student> max = students.stream().max(Comparator.comparingInt(Student::getAge));
        Optional<Student> min = students.stream().min(Comparator.comparingInt(Student::getAge));
        if (max.isPresent()) {
            System.out.println("max：" + max.get());
        }
        if (min.isPresent()) {
            System.out.println("min：" + min.get());
        }
        /* count */
        long count = students.stream().filter(s1 -> s1.getAge() < 45).count();
        System.out.println("count：" + count);
        /* reduce */
        Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b);
        System.out.println("reduce：" + reduce);
        Integer reduce2 = students.stream().map(Student::getAge).reduce(BigDecimal.ROUND_UP, (a, b) -> a + b);
        System.out.println("reduce求年龄之和：" + reduce2);
        /* 分页，从0开始取前5条 */
        List<Student> list = students.stream().skip(0).limit(5).collect(Collectors.toList());
        System.out.println(list);
    }

    /* 高级集合类及收集器 */
    public static void test2() {
        List<Student> students1 = new ArrayList<>();
        students1.add(Student.builder().name("张三").age(20).stature(170).speciality(SpecialityEnum.SING).build());
        students1.add(Student.builder().name("李四").age(30).stature(180).speciality(SpecialityEnum.DANCE).build());
        students1.add(Student.builder().name("王五").age(40).stature(190).speciality(SpecialityEnum.RUNNING).build());
        OutstandingClass ostClass1 = new OutstandingClass("一班", students1);
        //复制 students1，并移除一个学生
        List<Student> students2 = new ArrayList<>(students1);
        students2.remove(BigDecimal.ROUND_UP);
        OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
        /* maxBy */
        OutstandingClass maxBy = Stream.of(ostClass1, ostClass2)
                .collect(Collectors.maxBy(Comparator.comparingInt(e ->
                        e.getStudents().size()
                ))).get();
        System.out.println("maxBy：" + maxBy);
        /* averagingInt */
        Double averagingInt = Stream.of(ostClass1, ostClass2)
                .collect(Collectors.averagingInt(e -> e.getStudents().size()));
        System.out.println("averagingInt：" + averagingInt);
        /* partitioningBy */
        Map<Boolean, List<Student>> partitioningBy = students1.stream().collect(Collectors.partitioningBy(student -> student.getSpeciality().equals(SpecialityEnum.SING)));
        System.out.println("partitioningBy：" + partitioningBy);
        /* groupingBy */
        Map<SpecialityEnum, List<Student>> groupingBy = students1.stream().collect(Collectors.groupingBy(Student::getSpeciality));
        System.out.println("groupingBy：" + groupingBy);
        /* joining */
        String joining = students1.stream().map(Student::getName).collect(Collectors.joining(",", "[", "]"));
        System.out.println("joining：" + joining);
    }

}
